项目介绍
需求分析
让用户查看当地天气、查询异地天气的时看到正能量文字,元气满满的开始新的一天。
本程序共分为三个页面:欢迎页面,天气预览界面,城市天气查询界面。
需求
天气预览界面:定位天气展示【1 获取当前经纬度位置 2 根据位置获取天气、城市信息 3将信息展示在视图】
城市天气查询界面:用户查询天气【1展示当前城市 2输入框输入查询城市的名称 3按下查询按钮-获取名称至页面1,销毁页面2 】
采用了MVC模式
model部分负责数据,我们构建天气类,属性包括:温度、城市、condition,以及计算属性——icon、words,他们需要根据condition属性来确定。比如晴天对于icon为小太阳、文字对于“天晴是你的心情”。
controller负责两个页面中的业务逻辑:从model中取数据,然后返回给view。
最终在view上展示所需天气及其文字信息。
遇到的困难
页面跳转传值
页面跳转传值部分。【功能:按页面1右上角按钮,跳转到页面二,页面二展示当前city;用户输入目标city,按查询后跳转回页面一,展示查询city的天气信息】
segue导航正向传值较容易,3步骤。1在prepare函数部分获取segue的identifier【转换箭头】,2使用as!强制转化,实例化该segue的destination页面vc,3使用实例化的vc进行传值。这样就可以在下一个页面使用本页面中的“所在城市”的信息了。
而反向传值就不同。如果采用control+drag方式,从页面二的button到页面一加上转换箭头,这样只会再重新生成新的页面一,定位到本地天气;而不是预想的回到原先页面,重新展示所搜索城市的信息。
所以需要自定义protocol,使用delegate实现导航的反向传值。
在页面二需要:3个步骤来自定义协议portocol,实现【按下查找城市按钮,获取输入的city值】的功能。
1自定义协议,安排协议中的方法(获取输入的city,传给页面一),2 声明协议属于页面二中的delegate变量 3规定在哪里触发协议中的事件。
在页面一种需要:3个步骤来实现协议,实现【获取页面二中city的值,并展示于本页面】的功能。
1遵守协议 2 实现协议中的方法(获取city值,根据值获取温度对象的所有信息,展示与本页面)3 第二个页面vc的事件函数委托delegate给self实现。
获取当前位置的天气
1 委托本页面,实现定位协议中的请求位置的方法,获得经纬度。(难点)
2 根据经纬度信息,使用Alamofire请求API来获取天气数据;
3 利用SwiftJSON解析生成数据;
4 给weather对象赋值;
5 再使用weather对象中的天气、文字信息更新页面。
–
使用了定位协议CLLocationManagerDelegate的方法。
1 遵守定位协议 2 实例化定位管理器CLLocationManager 3 实现协议中的方法(获取当前的经纬度)4locationManager委托本页面
当manager请求位置的时候,则系统自动调用manager方法,在该方法里获得经纬度。
知识点
protocol-delegate:类似java中的接口与实现
协议——工具间,协议中的方法——工具,实例化的对象——老板,本页面self——打工仔,委托——老板让打工仔干活
计算属性
model中的计算属性——compute属性 某个属性需要根据另一个属性来确定,我们定义其为计算属性
如根据天气情况属性——晴天,得到对应的icon和words:icon为小太阳、wors为“天晴是你的心情”。
第三方库的CocoaPods安装的使用
Alamofire:完成http请求天气数据
SwiftJSON:解析、生成数据
extension代码优化
目的:提高代码可读性。为日后重构代码打下了良好的基础。
场景:1 私有的辅助函数 ;2 遵守协议(实现某个协议的方法放到一个 extension 中);3 模型(Model用结构体, 使用extension 将 Model 的 属性 和 基于属性的计算计算属性分离 )
项目布局
UI设计
页面一
创建项目的时候需要取消左右旋转
背景图约束:
上下左右相对于View都是0
背景图片填充方式为Aspect Fill拉伸
中间图片
Label 左边自适应
页面二
StackView自适应页面的宽度:
选中StackView后control+drag至背景图
是的stackView:页面的比例为2:5
错误:该页面无法到达,需要添加跳转
需要按下按钮,跳转至新的页面:选中按钮,control+drag 至第二页面,选择show(直接跳转)/Present modally(从下往上弹出),生成连接。
启动页面
同理自行设计
依赖管理工具CocoaPods
介绍
- 什么是CocoaPods
CocoaPods是OS X和iOS下的一个第三类库管理工具,通过CocoaPods工具我们可以为项目添加被称为“Pods”的依赖库(这些类库必须是CocoaPods本身所支持的),并且可以轻松管理其版本。
- CocoaPods的好处
1、在引入第三方库时它可以自动为我们完成各种各样的配置,包括配置编译阶段、连接器选项、甚至是ARC环境下的-fno-objc-arc配置等。
2、使用CocoaPods可以很方便地查找新的第三方库,这些类库是比较“标准的”,而不是网上随便找到的,这样可以让我们找到真正好用的类库。
- 需要第三方库的时候,三个步骤:
0、安装cocoapos
1、command+N导入项目
2、自动创建podfile文件,在该文件写入pod ‘工具包名称’,点击instal下载
3、项目安装配置第三方库完成,点击r.xcworkspace文件进入项目
在CocoaPods中安装第三方库SVProgressHUD
- 导入
- 写需要的第三方库,安装
- 安装配置完成。安装配置过功能包之后,打开项目都是使用Weather.xcworkspace文件
获取经纬度
请求用户给予权限的窗口未弹出,报如下错误
原因是:弹框弹出时,需要给到一个描述给用户,说明为什么需要该信息,在info.plist中设置
问题解决:
https://swift.gg/2017/02/13/requesting-permissions-core-location-tutorial/
API 使用网络请求功能包Alamofire完成http请求获取天气数据
API:应用程序接口(API:Application Program Interface)
https://openweathermap.org/api
选择合适的API
根据经纬度获取天气需要的信息
HTTP+字典Dictionary+JSON+第三方功能包SwiftyJSON
字典类型:键值对构成
let dict:[String:Any] = [“name”:”zhangsan”,”age”:18]
创建Weather模型+把获取到的数据显示到页面+计算属性初探
https://openweathermap.org/weather-conditions
代码优化-把功能块分离出来变成函数+extension
view连接controller+segue导航正向传值+三种as+delegate实现导航的反向传值
view连接controller
选择cocoaTouch class,创建controller,选择页面二,建立连接。
segue导航正向传值
1、选中转换箭头,设置该转换的id
2、通过在segue的函数中的segue.identifier找到究竟是哪一个【转换箭头】
3、根据转换箭头,使用 sugue.destination 找到箭头的目的地页面
4、使用as!强制转换获取页面vc(实例化的对象)
5、利用vc页面,传值
自定义protocol和delegate实现导航的反向传值
页面二:selectCityController
- 自定义协议,安排了协议的方法
- 工具属于谁的——页面二中的delegate变量的
- 规定在哪里触发时间——按下查找城市按钮
页面一:viewController
- 遵守协议——领取工具
- 实现协议中规定的方法——去干活。原因:想要用协议的方法,获取里面的参数
- 委托——指导谁(vc)委托给本页面(self)的
转型——三种as
as 向上转型:安全,一般直接使用Int(3.2),所以不常用 3.2 as Int
as? 向下转型:需要判断 if let,若转换不了,得到nil
1 | if let vc = segue.destination as? SelectCityController |
as! 向下转型
1 | let vc = segue.destination as! SelectCityController |
完成用户查询天气的功能
光标的出现和收起
1 | override func viewDidLoad() { |
源码
1 |